﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace CPPEI.WebApi
{

    public class UIDToken
    {
        public static u FromToken(string token)
        {
            string uString = DES.DecryptString(token, "jzsaaaaa");

            u uObj = u.fromString(uString);
            return uObj;
        }

        public static string ToToken(u uObj)
        {
            string uString = u.toString(uObj);
            //byte[] decompressTokenData = System.Text.Encoding.UTF8.GetBytes(token2);
            //byte[] tokenData = ZipHelper.Compress(uString);
            //string token = Convert.ToBase64String(tokenData);
            string token = DES.EncryptString(uString, "jzsaaaaa");
            string token2 = DES.DecryptString(token, "jzsaaaaa");
            return token;
        }



        private  static byte[] SerializeToBinary(object obj)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(ms, obj);

                byte[] resbytes = new byte[ms.Length];

                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(resbytes, 0, (int)ms.Length);

                return resbytes;
            }
        }

        private static object DeserializeFromBinary(byte[] data)
        {
            using (MemoryStream ms = new MemoryStream(data))
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                return binaryFormatter.Deserialize(ms);
            }
        }

        class DES
        {
            // 创建Key
            public string GenerateKey()
            {
                DESCryptoServiceProvider desCrypto = (DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
                return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
            }
            // 加密字符串
            public static string EncryptString(string sInputString, string sKey)
            {
                byte[] data = Encoding.UTF8.GetBytes(sInputString);
                DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
                DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                ICryptoTransform desencrypt = DES.CreateEncryptor();
                byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);
                //string s1 = BitConverter.ToString(result);

                //string s3 = s1.Replace("-", string.Empty);
                string s2 = toBitString(result);

                return s2;
            }

            // 解密字符串
            public static string DecryptString(string sInputString, string sKey)
            {
                //string[] sInput = sInputString.Split('-');
                //byte[] data = new byte[sInput.Length];
                //for (int i = 0; i < sInput.Length; i++)
                //{
                //    data[i] = byte.Parse(sInput[i], NumberStyles.HexNumber);
                //}

                byte[] data = new byte[sInputString.Length / 2];
                for (int i = 0; i < data.Length; i++)
                {
                    data[i] = byte.Parse(sInputString.Substring(i* 2,2), NumberStyles.HexNumber);
                }
                DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
                DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                ICryptoTransform desencrypt = DES.CreateDecryptor();
                byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);
                return Encoding.UTF8.GetString(result);
            }

            internal static string toBitString(byte[] data)
            {
                StringBuilder builder = new StringBuilder();
                for (int index = 0; index < data.Length; index++)
                {
                    builder.AppendFormat("{0:X2}", data[index]);
                }
                return builder.ToString();
            }
        }

        private class ZipHelper
        {
            /// <summary>  
            /// 解压  
            /// </summary>  
            /// <param name="Value"></param>  
            /// <returns></returns>  
            //public static DataSet GetDatasetByString(string Value)
            //{
            //    DataSet ds = new DataSet();
            //    string CC = GZipDecompressString(Value);
            //    System.IO.StringReader Sr = new StringReader(CC);
            //    ds.ReadXml(Sr);
            //    return ds;
            //}
            /// <summary>  
            /// 根据DATASET压缩字符串  
            /// </summary>  
            /// <param name="ds"></param>  
            /// <returns></returns>  
            public static string GetStringByDataset(string ds)
            {
                return GZipCompressString(ds);
            }
            /// <summary>  
            /// 将传入字符串以GZip算法压缩后，返回Base64编码字符  
            /// </summary>  
            /// <param name="rawString">需要压缩的字符串</param>  
            /// <returns>压缩后的Base64编码的字符串</returns>  
            public static string GZipCompressString(string rawString)
            {
                if (string.IsNullOrEmpty(rawString) || rawString.Length == 0)
                {
                    return "";
                }
                else
                {
                    byte[] rawData = System.Text.Encoding.UTF8.GetBytes(rawString.ToString());
                    byte[] zippedData = Compress(rawData);
                    return (string)(Convert.ToBase64String(zippedData));
                }

            }
            /// <summary>  
            /// GZip压缩  
            /// </summary>  
            /// <param name="rawData"></param>  
            /// <returns></returns>  
            public static byte[] Compress(byte[] rawData)
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Compress);
                    compressedzipStream.Write(rawData, 0, rawData.Length);
                    compressedzipStream.Close();
                    return ms.ToArray();
                }
            }
            /// <summary>  
            /// 将传入的二进制字符串资料以GZip算法解压缩  
            /// </summary>  
            /// <param name="zippedString">经GZip压缩后的二进制字符串</param>  
            /// <returns>原始未压缩字符串</returns>  
            public static string GZipDecompressString(string zippedString)
            {
                if (string.IsNullOrEmpty(zippedString) || zippedString.Length == 0)
                {
                    return "";
                }
                else
                {
                    byte[] zippedData = Convert.FromBase64String(zippedString.ToString());
                    return (string)(System.Text.Encoding.UTF8.GetString(Decompress(zippedData)));
                }
            }
            /// <summary>  
            /// ZIP解压  
            /// </summary>  
            /// <param name="zippedData"></param>  
            /// <returns></returns>  
            public static byte[] Decompress(byte[] zippedData)
            {
                MemoryStream ms = new MemoryStream(zippedData);
                GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Decompress);
                MemoryStream outBuffer = new MemoryStream();
                byte[] block = new byte[1024];
                while (true)
                {
                    int bytesRead = compressedzipStream.Read(block, 0, block.Length);
                    if (bytesRead <= 0)
                        break;
                    else
                        outBuffer.Write(block, 0, bytesRead);
                }
                compressedzipStream.Close();
                return outBuffer.ToArray();
            }
        }  
    }

    /// <summary>
    /// user identity for client
    /// </summary>
    [Serializable]
    public class u
    {
        /// <summary>
        /// account-id
        /// </summary>
        public int a { get; set; }

        /// <summary>
        /// timeout time
        /// yy-MM-dd HH:mm
        /// </summary>
        public string b { get; set; }

        /// <summary>
        /// validate string
        /// md5(a+b+c+d) == e
        /// </summary>
        public string e { get; set; }

        public bool Validate()
        {
            string correctToken = this.convertToMd5(string.Format("{0},{1}", this.a, this.b));
            if (string.Equals(correctToken, this.e))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 验证是否超时
        /// </summary>
        /// <returns></returns>
        public bool ValidateTimeout()
        {
            DateTime time = Convert.ToDateTime(b);
            if (time > DateTime.Now)
            {
                return true;
            }
            return false;
        }

        public static u build(int a, string b)
        {
            u uObj = new u();
            uObj.a = a;
            uObj.b = b;
            uObj.e = uObj.convertToMd5(string.Format("{0},{1}", uObj.a, uObj.b));
            return uObj;
        }

        public static string toString(u uObj)
        {
            return string.Format("{0},{1},{2}",
                uObj.a,
                uObj.b,
                uObj.e);
        }

        public static u fromString(string str)
        {
            string[] strArr = str.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            u uObj = new u();
            uObj.a = Convert.ToInt32(strArr[0]);
            //uObj.b = strArr[1];
            //uObj.c = Convert.ToInt64(strArr[2]);
            uObj.b = strArr[1];
            uObj.e = strArr[2];
            return uObj;
        }

        private string convertToMd5(string sourceStr)
        {
            MD5 newMd5 = new MD5CryptoServiceProvider();
            byte[] sourceBit = Encoding.Default.GetBytes(sourceStr);
            byte[] directBit = newMd5.ComputeHash(sourceBit);

            return toBitString(directBit, 8);
        }
        internal static string toBitString(byte[] data, int length)
        {
            StringBuilder builder = new StringBuilder();
            for (int index = 0; index < data.Length && index < length; index++)
            {
                builder.AppendFormat("{0:X00}", data[index]);
            }
            return builder.ToString();
        }
    }
}
